#pragma once
#include <list>
#include <memory.h>
#include "resource.h"
#include "triangle.h"
#include "boundingbox.h"
#include "texture.h"
#include <d3dx9.h>

/**
 * Klasa siatki.
 *
 * @author Krzysztof Klein
 * @version 0.1
 */
class Mesh : public Resource
{

	/**
	 * Element siatki
	 */
	class Subset
	{
		/**
		 * Material
		 */
		D3DMATERIAL9 material;

		/**
		 * Tekstura
		 */
		Texture* texture;

	public:

		/**
		 * Konstruktor domyslny
		 */
		Subset() : texture(NULL) { }

		/**
		 * Destruktor
		 */
		virtual ~Subset()
		{
			if(texture)
				texture->release();
		}


		/**
		 * Zwraca material
		 */
		inline D3DMATERIAL9 getMaterial() const { return material; }

		/**
		 * Ustawia material
		 */
		inline void setMaterial(const D3DMATERIAL9 &mat)
			{ memcpy(&material, &mat, sizeof(D3DMATERIAL9)); }


		/**
		 * Zwraca teksture
		 */
		inline Texture* getTexture() const { return texture; }

		/**
		 * Ustawia teksture
		 */
		inline void setTexture(Texture* t)
		{
			if(texture)
				texture->release();
			texture = t;
			if(texture)
				texture->addRef();
		}


		/**
		 * Ustawia material i teksture na danym urzadzeniu
		 */
		inline void apply(LPDIRECT3DDEVICE9 device) const
		{
			device->SetMaterial(&material);
			if(texture)
				device->SetTexture(0, texture->getTexture());
			else
				device->SetTexture(0, NULL);
		}

	};


	/**
	 * Liczba elementow siatki
	 */
	int subsetCount;

	/**
	 * Tablica elementow siatki
	 */
	Subset* subsets;


	/**
	 * Siatka D3DX
	 */
	LPD3DXMESH mesh;


	/**
	 * Lista trojkatow siatki
	 */
	std::list<Triangle*> triangles;


	/**
	 * Prostopadloscian otaczajacy
	 */
	BoundingBox boundingBox;

public:

	/**
	 * Konstruktor domyslny
	 */
	Mesh();

	/**
	 * Destruktor
	 */
	~Mesh();

	/**
	 * Renderuje siatke
	 *
	 * @param device Urzadzenie Direct3D
	 */
	void render(LPDIRECT3DDEVICE9 device) const;
	
	/**
	 * Laduje siatke bezposrednio z danych pliku X.
	 */
	bool loadFromXof(LPD3DXFILEDATA xofFileData);

	/**
	 * Prostopadloscian otaczajacy
	 */
	const BoundingBox& getBoundingBox() const { return boundingBox; }

	/**
	 * Zwraca liczbe podsiatek
	 */
	int getSubsetCount() const { return subsetCount; }

	/**
	 * Ustawia teksture danej podsiatki
	 */
	void setSubsetTexture(int subsetId, Texture* texture);

	/**
	 * Lista trojkatow siatki
	 */
	const std::list<Triangle*>& getTriangles() const { return triangles; }

private:

	/**
	 * Typ zasobu
	 */
	Type getType() const { return Resource::MeshResource; }

	/**
	 * Laduje siatke z zasobu.
	 * Scala wszystkie ramki i siatki w jedna.
	 */
	virtual bool load();

	/**
	 * ...
	 */
	virtual void unload();


	/**
	 * Generuje liste trojkatow na podstawie siatki.
	 */
	bool genTriangleList();

};
